/**
 * Title: jFamilyTree provider
 * Description: jFamilyTree Provider
 * Version: provider
 * Copyright: (c) 2001-2008
 * Terms of use:see license agreement at http://treebolic.sourceforge.net/en/license.htm
 * Author: Bernard Bou
 * Company: bsys
 * Update: Mon Mar 10 00:00:00 CEST 2008
 */
package jFamilyTree.provider.xml.dom;

import java.io.IOException;
import java.net.URL;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.sax.SAXSource;
import javax.xml.transform.stream.StreamSource;

import org.w3c.dom.Document;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLReaderFactory;

/**
 * DOM Parser
 * 
 * @author Bernard Bou
 */
public class Parser
{
	/**
	 * Validate XML
	 */
	protected boolean validate;

	/**
	 * Constructor
	 */
	public Parser()
	{
		this(false);
	}

	/**
	 * Constructor
	 */
	public Parser(boolean thisValidateFlag)
	{
		validate = thisValidateFlag;
	}

	/**
	 * Make document
	 * 
	 * @param thisUrl
	 *        in data url
	 * @param thisResolver
	 *        entity resolver
	 * @return DOM document
	 */
	public Document makeDocument(URL thisUrl, EntityResolver thisResolver)
	{
		ErrorDialog thisHandler = new ErrorDialog();
		try
		{
			DocumentBuilder thisBuilder = makeDocumentBuilder();
			thisBuilder.setErrorHandler(thisHandler);
			if (thisResolver != null)
				thisBuilder.setEntityResolver(thisResolver);
			Document thisDocument = thisBuilder.parse(thisUrl.openStream());
			return thisDocument;
		}
		catch (IOException e)
		{
			System.err.println("Dom parser: " + e.toString());
		}
		catch (SAXException e)
		{
			System.err.println("Dom parser: " + e.toString());
		}
		catch (ParserConfigurationException e)
		{
			System.err.println("Dom parser: " + e.toString());
		}
		catch (Exception e)
		{
			System.err.println("Dom parser: " + e.toString());
		}
		finally
		{
			thisHandler.terminate();
		}
		return null;
	}

	/**
	 * Make Document builder
	 * 
	 * @return document builder
	 * @throws ParserConfigurationException
	 */
	private DocumentBuilder makeDocumentBuilder() throws ParserConfigurationException
	{
		DocumentBuilderFactory thisFactory = DocumentBuilderFactory.newInstance();
		thisFactory.setCoalescing(true);
		thisFactory.setIgnoringComments(true);
		thisFactory.setNamespaceAware(false);
		thisFactory.setIgnoringElementContentWhitespace(true);
		thisFactory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", validate);
		thisFactory.setValidating(validate);
		return thisFactory.newDocumentBuilder();
	}

	/**
	 * Document
	 * 
	 * @param thisIn
	 *        in data url
	 * @param thisXslt
	 *        xslt url
	 * @param thisResolver
	 *        entity resolver, null if none
	 * @return DOM document
	 * @throws TransformerException
	 * @throws IOException
	 */
	public Document makeDocument(URL thisIn, URL thisXslt, EntityResolver thisResolver)
	{
		try
		{
			// xsl
			Source thisXslSource = new StreamSource(thisXslt.openStream());

			// in
			Source thisSource = null;
			if (thisResolver == null)
				thisSource = new StreamSource(thisIn.openStream());
			else
			{
				XMLReader thisReader = XMLReaderFactory.createXMLReader();
				thisReader.setEntityResolver(thisResolver);
				thisSource = new SAXSource(thisReader, new InputSource(thisIn.openStream()));
			}

			// out
			DOMResult thisResult = new DOMResult();

			// transform
			TransformerFactory thisFactory = TransformerFactory.newInstance();
			Transformer thisTransformer = thisFactory.newTransformer(thisXslSource);
			thisTransformer.setParameter("http://xml.org/sax/features/validation", false);
			thisTransformer.transform(thisSource, thisResult);

			return (Document) thisResult.getNode();
		}
		catch (IOException e)
		{
			System.err.println("Dom parser: " + e.getMessage());
		}
		catch (TransformerConfigurationException e)
		{
			System.err.println("Dom parser: " + e.getMessage());
		}
		catch (TransformerException e)
		{
			System.err.println("Dom parser: " + e.getMessage());
		}
		catch (Exception e)
		{
			System.err.println("Dom parser: " + e.getMessage());
		}
		return null;
	}
}
